package log

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"gitee.com/shibingli/fastweb/utils"
	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var (
	DefaultLogFile = "/tmp/fastweb/fastweb.log"
)

type Logger struct {
	noCopy NoCopy

	*zap.Logger
}

func NewLogger(level zapcore.Level, maxSize, maxAge, maxBackups int, logFile ...string) (*Logger, error) {

	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "T",
		LevelKey:       "L",
		NameKey:        "LOG",
		CallerKey:      "F",
		MessageKey:     "M",
		StacktraceKey:  "S",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
		EncodeName:     zapcore.FullNameEncoder,
	}

	var zws zapcore.WriteSyncer

	if len(logFile) > 0 && len(strings.TrimSpace(logFile[0])) > 0 {
		DefaultLogFile = logFile[0]

		logDir := filepath.Dir(DefaultLogFile)

		if !utils.IsDir(logDir) {
			if err := os.Mkdir(logDir, os.ModePerm); nil != err {
				return nil, err
			}
		}

		zws = zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&lumberjack.Logger{
			Filename:   DefaultLogFile,
			MaxSize:    maxSize,
			MaxBackups: maxBackups,
			MaxAge:     maxAge,
			Compress:   true,
		}))
	} else {
		zws = zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout))
	}

	logger := zap.New(zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig),
		zws,
		zap.NewAtomicLevelAt(level),
	), zap.AddCaller(), zap.Development())

	defer func() {
		_ = logger.Sync()
	}()

	return &Logger{
		Logger: logger,
	}, nil
}

func RFC3339TimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString(t.Format(time.RFC3339))
}

func (l *Logger) Printf(format string, args ...interface{}) {
	l.Logger.Info("DiTing",
		zap.String("Msg", fmt.Sprintf(format, args...)),
	)
}
